﻿#ifndef CAMERAATTRIBUTE_H
#define CAMERAATTRIBUTE_H
#include "Infra/Function.h"
#include "GenICam/AcquisitionControl.h"
#include "GenICam/AnalogControl.h"
#include "GenICam/ImageFormatControl.h"
#include "GenICam/ISPControl.h"
#include <sstream>
#include <map>
#include "GenICam/System.h"
#include <QtWidgets>

//#define EDIT_CHANGE   0
//#define SLIDER_CHANGE 1

struct XmlCfgItem
{
    std::string name;
    std::string value;
};

enum EAttrIdx
{
    SATURATION = 0,
    FRAMERATE  = 1,
    EXPOSURETIME = 2,
    GAINRAW = 3,
    GAMMA = 4,
    BRIGHTNESS = 5,
    SHARPNESS = 6,
    HUE = 7,
    WHITEBALANCE_R = 8,
    WHITEBALANCE_G = 9,
    WHITEBALANCE_B = 10,
    PICFORMAT = 11,
    AUTOEXPOSURE = 12,
    EXPOSUREMODE = 13,
    GAINAUTO = 14,
    BLACKLEVEL = 15,
    PLAYMODE = 16,
    REVERSEX = 17,
    REVERSEY = 18,
    TRIGGERMODE = 19,
    SOFTTRIGGER = 20,
    MUTIFRAMECNT = 21,
    DIGITALSHIFT = 22,
	CONTRAST = 23,
	CONTRASTTHRESHOLD = 24,
};

class IAttrCtrlBase
{
public:
  //  IAttrCtrlBase();
    // 属性控件初始化
    virtual void init(Dahua::GenICam::ICameraPtr camera) = 0;

    // 获取窗口对象，用于Edit控件回车响应
 //   virtual CWnd* getWnd() = 0;

    // 更新自身的状态
    virtual void updataStatus(Dahua::GenICam::ICameraPtr camera) {Q_UNUSED(camera)}

    // 更新属性参数
    virtual void updataValue(Dahua::GenICam::ICameraPtr camera, int param) = 0;

    // 导入属性参数
    void readCfg(Dahua::GenICam::ICameraPtr camera, std::vector< XmlCfgItem >& itemVec)
    {
        std::vector< XmlCfgItem >::iterator it = itemVec.begin();
        for (; it != itemVec.end(); ++it)
        {
            if ((*it).name == getAttrName())
            {
                updataValue(camera, (*it).value);
				break;
            }
        }
    }

    // 导出属性参数
    virtual void writeCfg(Dahua::GenICam::ICameraPtr camera, std::vector< XmlCfgItem >& itemVec) = 0;

    // 虚析构
    virtual ~IAttrCtrlBase() {}

protected:

    // 获取属性名称
    virtual std::string getAttrName() = 0;

    // 更新属性参数
    virtual void updataValue(Dahua::GenICam::ICameraPtr camera, std::string const& val) = 0;
};



// 该类是滑动条与文本框结合的控件类抽象
template<typename ValType,         // 参数类型
         typename R,               // GenICam定义的参数节点类型 如 IIntNode
         typename GetValueMethod  // 获取参数节点的方法 GetValueMethod::getValuePtr(Dahua::GenICam::ICameraPtr& camera)
        >
class TSliderEditAttr : public IAttrCtrlBase
{
public:

    // 构造函数
    // \param[in] hwd控件所属的窗口类指针
    TSliderEditAttr(QSlider *slider, QLineEdit *edit)
    {
        _sliderCtrl = slider;
        _editCtrl = edit;
    }

    // 虚析构函数
    virtual ~TSliderEditAttr() {}

    // 继承IAttrCtrlBase的初始化接口
    virtual void init(Dahua::GenICam::ICameraPtr camera)
    {
        if (NULL == camera)
            return;

        // 获取参数节点
        R valuePtr = GetValueMethod::getValuePtr(camera);
        if (!valuePtr.isValid())
        {
            _editCtrl->setEnabled(false);
            _sliderCtrl->setEnabled(false);
            return;
        }

        // 获取最大，最小值以及当前值
        ValType max, min, val;
        valuePtr.getMaxVal(max);
        valuePtr.getMinVal(min);
        valuePtr.getValue(val);
        _val = val;
	//	qDebug() << min << max << val;
        // 初始化滑动条与文本框
		if (_sliderCtrl)
		{
			_sliderCtrl->setRange((int)min, round(max));
			_sliderCtrl->setValue((int)val);
		}
        
        if (_editCtrl)
        {
			_editCtrl->setText(QString::number(val));
        }
    }

    // 更新数据 两个地方调用 1、滑动条变化 2、编辑窗口收到回车事件
    virtual void updataValue(Dahua::GenICam::ICameraPtr camera, int type)
    {
        TSliderEditAttr::setValue(camera, type != 0);
    }

    // 更新自身的状态
    virtual void updataStatus(Dahua::GenICam::ICameraPtr camera)
    {
        R value = GetValueMethod::getValuePtr(camera);
        if (!value.isValid())
            return;

        if (!value.isWriteable())
        {
            _editCtrl->setEnabled(false);
            _sliderCtrl->setEnabled(false);
        }
        else
        {
            _editCtrl->setEnabled(true);
            _sliderCtrl->setEnabled(true);
        }
    }

    // 导出属性参数
    virtual void writeCfg(Dahua::GenICam::ICameraPtr camera, std::vector< XmlCfgItem >& itemVec)
    {
        R value = GetValueMethod::getValuePtr(camera);
        if (!value.isValid())
            return;

        XmlCfgItem item;
        item.name = getAttrName();

        ValType val;
        value.getValue(val);
        std::stringstream ss;
        ss << val;
        item.value = ss.str();

        itemVec.push_back(item);
		qDebug() << "writeCfg:"<< item.name.c_str() << ss.str().c_str();
    }

    // 更新属性参数，用于xml文件的参数更新
    virtual void updataValue(Dahua::GenICam::ICameraPtr camera, std::string const& strVal)
    {
        ValType val;
        std::stringstream ss;
        ss << strVal;
        ss >> val;

        syncValue(camera, val);
    }

    // 设置数值，用于
    void setValue(Dahua::GenICam::ICameraPtr& camera, bool slider = true)
    {
        if (NULL == camera)
            return;

        ValType val;
        if (slider)
        {
            val = (ValType)_sliderCtrl->value();
        }
        else
        {
            QString text = _editCtrl->text();
//            std::stringstream ss;
//            ss << text;
//            ss >> val;
            val = text.toInt();
            R valuePtr = GetValueMethod::getValuePtr(camera);
            ValType max, min, val2;
            valuePtr.getMaxVal(max);
            valuePtr.getMinVal(min);
            valuePtr.getValue(val2);
            if (val>max)
            {
                val = max;
//                CString cs;
//                cs.Format(_T("%d"), val);
//                _editCtrl->SetWindowText(cs);
                _editCtrl->setText(QString::number(val));
            }
            else if (val < min)
            {
                val = min;
//                CString cs;
//                cs.Format(_T("%d"), val);
//                _editCtrl->SetWindowText(cs);
                _editCtrl->setText(QString::number(val));
            }

        }

        syncValue(camera, val);
    }

    // 获取窗口对象，用于Edit控件回车响应
//    virtual CWnd* getWnd()
//    {
//        return (CWnd*)_editCtrl;
//    }

protected:

    void syncValue(Dahua::GenICam::ICameraPtr& camera, ValType val)
    {
        R value = GetValueMethod::getValuePtr(camera);
        if (!value.isValid())
            return;

        if (_val != val && value.isWriteable())
        {
            _val = val;
            value.setValue(val);
        }

//        std::stringstream ss;
//        ss << _val;
//        CString cs;
//        cs.Format(_T("%d"), _val);
        if (_editCtrl)
        {
            //_editCtrl->SetWindowText(cs);
            _editCtrl->setText(QString::number(_val));
        }

        if (_sliderCtrl)
        {
            _sliderCtrl->setValue((int)_val);
          //  _sliderCtrl->SetPos((int)_val);
        }

    }

    QSlider *_sliderCtrl;
    QLineEdit *_editCtrl;
  //  CSliderCtrl* _sliderCtrl;
//    CEdit*       _editCtrl;
    ValType      _val;
};


typedef Dahua::Memory::TSharedPtr<IAttrCtrlBase> AttrCtrlBasePtr;
typedef std::map< int, AttrCtrlBasePtr > AttrCtrlMap;

struct BrightnessAttr
    : public TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, BrightnessAttr>
{
    typedef TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, BrightnessAttr> base_type;

    BrightnessAttr(QSlider *slider, QLineEdit *edit)
        : base_type(_sliderCtrl, _editCtrl)
    {
        _sliderCtrl = slider;
        _editCtrl = edit;
    }

    static Dahua::GenICam::CIntNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
    {
        Dahua::GenICam::IISPControlPtr ptr =
            Dahua::GenICam::CSystem::getInstance().createISPControl(camera);
        return ptr->brightness();
    }

    // 获取属性名称
    virtual std::string getAttrName()
    {
        return "Brightness";
    }
};

struct DigitalShiftAttr
    : public TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, DigitalShiftAttr>
{
    typedef TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, DigitalShiftAttr> base_type;

    DigitalShiftAttr(QSlider *slider, QLineEdit *edit)
        : base_type(_sliderCtrl, _editCtrl)
    {
        _sliderCtrl = slider;
        _editCtrl = edit;
    }

    static Dahua::GenICam::CIntNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
    {
        Dahua::GenICam::IISPControlPtr ptr =
            Dahua::GenICam::CSystem::getInstance().createISPControl(camera);
        return ptr->digitalshift();
    }

    // 获取属性名称
    virtual std::string getAttrName()
    {
        return "Digitalshift";
    }
};

struct ExposureTimeAttr
    : public TSliderEditAttr<double, Dahua::GenICam::CDoubleNode, ExposureTimeAttr>
{
    typedef TSliderEditAttr<double, Dahua::GenICam::CDoubleNode, ExposureTimeAttr> base_type;

    ExposureTimeAttr(QSlider *slider, QLineEdit *edit)
        : base_type(_sliderCtrl, _editCtrl)
    {
        _sliderCtrl = slider;
        _editCtrl = edit;
    }

    static Dahua::GenICam::CDoubleNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
    {
        Dahua::GenICam::IAcquisitionControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createAcquisitionControl(camera);
        return ptr->exposureTime();
    }

    // 获取属性名称
    virtual std::string getAttrName()
    {
        return "ExposureTime";
    }
};




struct ContrastAttr
	: public TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, ContrastAttr>
{
	typedef TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, ContrastAttr> base_type;

	ContrastAttr(QSlider *slider, QLineEdit *edit)
		: base_type(_sliderCtrl, _editCtrl)
	{
		_sliderCtrl = slider;
		_editCtrl = edit;
	}

	static Dahua::GenICam::CIntNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
	{
		Dahua::GenICam::IISPControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createISPControl(camera);
	//	Dahua::GenICam::IAnalogControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createAnalogControl(camera);
		return ptr->contrast();
	}

	// 获取属性名称
	virtual std::string getAttrName()
	{
		return "Contrast";
	}
};

struct ContrastThresholdAttr
	: public TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, ContrastThresholdAttr>
{
	typedef TSliderEditAttr<int64_t, Dahua::GenICam::CIntNode, ContrastThresholdAttr> base_type;

	ContrastThresholdAttr(QSlider *slider, QLineEdit *edit)
		: base_type(_sliderCtrl, _editCtrl)
	{
		_sliderCtrl = slider;
		_editCtrl = edit;
	}

	static Dahua::GenICam::CIntNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
	{
		Dahua::GenICam::IISPControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createISPControl(camera);
		//	Dahua::GenICam::IAnalogControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createAnalogControl(camera);
		return ptr->contrastThreshold();
	}

	// 获取属性名称
	virtual std::string getAttrName()
	{
		return "ContrastThreshold";
	}
};

struct GainRawAttr
	: public TSliderEditAttr<double, Dahua::GenICam::CDoubleNode, GainRawAttr>
{
	typedef TSliderEditAttr<double, Dahua::GenICam::CDoubleNode, GainRawAttr> base_type;

	GainRawAttr(QSlider *slider, QLineEdit *edit)
		: base_type(_sliderCtrl, _editCtrl)
	{
		_sliderCtrl = slider;
		_editCtrl = edit;
	}

	static Dahua::GenICam::CDoubleNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
	{
		Dahua::GenICam::IAnalogControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createAnalogControl(camera);
		return ptr->gainRaw();
	}

	// 获取属性名称
	virtual std::string getAttrName()
	{
		return "GainRaw";
	}
};

struct GammaAttr
	: public TSliderEditAttr<double, Dahua::GenICam::CDoubleNode, GammaAttr>
{
	typedef TSliderEditAttr<double, Dahua::GenICam::CDoubleNode, GammaAttr> base_type;

	GammaAttr(QSlider *slider, QLineEdit *edit)
		: base_type(_sliderCtrl, _editCtrl)
	{
		_sliderCtrl = slider;
		_editCtrl = edit;
	}

	static Dahua::GenICam::CDoubleNode getValuePtr(Dahua::GenICam::ICameraPtr& camera)
	{
		Dahua::GenICam::IAnalogControlPtr ptr = Dahua::GenICam::CSystem::getInstance().createAnalogControl(camera);
		return ptr->gamma();
	}

	// 获取属性名称
	virtual std::string getAttrName()
	{
		return "Gamma";
	}
};

#endif // CAMERAATTRIBUTE_H
